﻿//
// Copyright 2024 Exhunter Technology Co.Ltd2.
//

using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;

namespace X18.Framework.Core.Security.Encryptor
{
    /// <summary>
    /// RSA加密算法
    /// </summary>
    public class RsaEncryptor : IDataEncryptor
    {
        /// <summary>
        /// 默认公钥
        /// </summary>
        private static readonly string DefalutPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqWCX9T4t9oDEuetbnZIroQ2lfn8H99kbgO4zsZoaPqFEcO+P5vjjbBOkRpZbw8g35UGorP2FffhpgebTiSeI2Qn2Y7C60ExURnulvrojytP0u23wdS9gyk/ILg44+qZX0/NfLZKSbpSavhy9ENe3KXwb12Ht7H3x4VFglcZQ2zk6/YgqKlxeEp9m26wv2XCa+m56z5Q/4NC5ZO7/zL/Zsys6s2qkGLzivO5W0mJhMFXnpnGSGVvtVAZh8wLjcv85yNMVSXXTpFacL6HP9jlXhgiE72Ed3823DXGGGxUASP9uMLM7GkrIG2Lb4GFWNgiXR0NKF5F8bXOX5uZOvlJwVwIDAQAB";
        /// <summary>
        /// 默认公钥（字节类型）
        /// </summary>
        private static readonly byte[] DefalutPublicByteKey;

        /// <summary>
        /// 默认私钥
        /// </summary>
        private static readonly string DefalutPrivateKeyAlg = "1.2.840.113549.1.12.1.3";
        private static readonly byte[] DefalutPrivateKeySalt = { 0x7f, 0xa3, 0x5d, 0xe1, 0x2b, 0xd4, 0x89, 0xf0, 0x3c, 0x67 };
        private static readonly int DefalutPrivateKeyCount = 888;
        private static readonly char[] DefalutPrivateKeyPassword = "Xjv2db4POVCuRbIzd".ToCharArray();
        /// <summary>
        /// 默认私钥
        /// </summary>
        private static readonly string DefalutPrivateKey = "MIIE7DAeBgoqhkiG9w0BDAEDMBAECn+jXeEr1InwPGcCAgN4BIIEyHYgUuC8X0vuyqlFMTiNRKmn9dzuB4JJFxvRIiTR2il9qS1+Remn3/dcoY6A6iAwWrt1cOwBK8dr/hKUOXBOQ3rlwfWBJW6xF8aiH4ANS4cyoNID0XqYI7RZaIbrw+ci9Lg4E+TSGrfqssdRDbz8M0XwNaYPIDTD3fTt8mKsM5muz0LDc7J2EZ3UvZZQisy9n/QxDTCK5/vjRTDu5mmO9qYxZQl8rY86nrLMjFM3lN0hFLxoBdEjA6BZRpYz3uBEHWerSd70bJazebXKhccIgqZOiKFyZVEi9PrhEUnZQLxKNSmFgaxZRMnxIWyXCSXtXon1ircZuv4J89O4GdIpGfaE2D6oLqoxCAWaJvoKgLpULjlRWQjaZRvLvOI0HT5KO8HBDLVW7oRW1L5xKDKArExjT589R/4n1gEv2oWtJznUoB6QnSCkvjAyLYRyrRIe53pGP28UB82B81CNAZq267SEHhDog7Fe7DVtfnyU1LNIChPRGYeAEeGnPQ2XshXobXAqp2cDh/QCvVjnFpoHa72XpMGQkkoti47E8S9Vwgn8QEKSrxLfO0tPB2MM4xVOCuAk7oy+noP7g1YzoqA4Ifa0/cqDNMeUhTCfm70zJTYL/ckmAWojIsPKg0sSly0IWRs1s7xt+1n539d1AJ+I6t7L83QEMM7B2+ayUiqXbs+k5iUrxv/kdFDZnjKFe8ofCj7MO7i9hcK3k1WCzLCbt+vy3EEvPaGHrH7YaHxvYrNzwVu7FI3EHvjZQMcmlbMS5Y9vLjCB0azO2dT+S4TCH+xXLucYF8EY9TfquzYLC09gxECkPyNCeF0g77EmB7k+dF71SEOE3e73mf+rdzzumN5r5OzVPO/8RYdSsalPAalVvxJx7Khx7Gww4PZ9IpG7+alZLUg+wt4+d6hA3PIBUdb3kghDrv+ofZPmhcK5CKU8V8FC52OARXyYjHVwo1D2HXb1Z+T52b7WzAbAatJLuhp71ILyA9LsJxn7cuLPWDwaWasZ99KLJQkp2mPLsI+bWv0cPFd8NOPnbXvouG76zDP7wCzs+GqKnnWXvc005mBCCsyuDrQjkmldZgjT7OOVzSgoainElul8Y88v1djk1E6WpQSS8y9kGIbTfnpHLCfBZ+/sWhIaqaIyGsnbDYYPRzXy0osnbfMQiNo+4L68Tg/wf/MrjMIBNI+5Q5DAfFePcE7e7x9iLt+HXhn5NWm+0KhJp13m+w52QmWQIZnd52aqxVDRcluM4AX9eY8QIv5PGRrHgA4nw6a1pUlLSmY5Izcv9aqX5BS3C1o4I8POYpvudGngP146IDRpKyfbj+Tm/HtZ1/MHayjf7Wo4b5mZEIFoAX7mpQPA2AjFvoo0yT4PToazmXAnGZ4ET3sTjKGwErqy1y0CqbYsZzIlqsNUsXtGs32e5JewgW3mYF/bM7B3326diWXL9i8hsSxg4Iv4mK4d1YZLh9RkxYQp6RX6FQwghoWwRcPIF1AWtKN5BsCwF94mTbQ7xOVbIodqdE6aLqnFXC6y32jqNPz3JrLbar1YoUpJdpQ9UkG28J8acAQXtXtIuiUFvkVodTEGtwwOVwZlZrsiT4lYZnzUxuqZtm+4gvmjFbHtHjslwf3C41tSmXWjUuyc3Q==";
        /// <summary>
        /// 默认私钥（字节类型）
        /// </summary>
        private static readonly byte[] DefalutPrivateByteKey;

        static RsaEncryptor()
        {
            DefalutPublicByteKey = Convert.FromBase64String(DefalutPublicKey);
            DefalutPrivateByteKey = Convert.FromBase64String(DefalutPrivateKey);
        }

        public static KeyPair GetKeyPair()
        {
            RsaKeyPairGenerator keyGen = new RsaKeyPairGenerator();
            keyGen.Init(new KeyGenerationParameters(new SecureRandom(), 2048));
            AsymmetricCipherKeyPair keyPair = keyGen.GenerateKeyPair();
            // 获取公钥和私钥
            var publicKey = (RsaKeyParameters)keyPair.Public;
            var privateKey = (RsaPrivateCrtKeyParameters)keyPair.Private;
            // 公钥
            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
            Asn1Object publicKeyObject = publicKeyInfo.ToAsn1Object();
            // 私钥
            EncryptedPrivateKeyInfo privateKeyInfo = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(
                DefalutPrivateKeyAlg,
                DefalutPrivateKeyPassword,
                DefalutPrivateKeySalt,
                DefalutPrivateKeyCount,
                privateKey);
            Asn1Object privateKeyObject = privateKeyInfo.ToAsn1Object();
            // 返回
            KeyPair result = new KeyPair();
            result.PublicKey = publicKeyObject.GetEncoded();
            result.PrivateKey = privateKeyObject.GetEncoded();
            return result;
        }

        public static byte[] Encrypt(byte[] plainBytes, byte[] key = null)
        {
            IAsymmetricBlockCipher engine = new RsaEngine();
            // 设置公钥
            byte[] key0 = key ?? DefalutPublicByteKey;
            Asn1Object publicKeyObject = Asn1Object.FromByteArray(key0);
            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.GetInstance(publicKeyObject);
            AsymmetricKeyParameter publicKey = (RsaKeyParameters)PublicKeyFactory.CreateKey(publicKeyInfo);
            engine.Init(true, publicKey);
            // 加密
            byte[] result = engine.ProcessBlock(plainBytes, 0, plainBytes.Length);
            return result;
        }

        public static byte[] Decrypt(byte[] cipherBytes, byte[] key = null)
        {
            IAsymmetricBlockCipher engine = new RsaEngine();
            // 设置私钥
            byte[] key0 = key ?? DefalutPrivateByteKey;
            Asn1Object privateKeyObject = Asn1Object.FromByteArray(key0);
            EncryptedPrivateKeyInfo privateKeyInfo = EncryptedPrivateKeyInfo.GetInstance(privateKeyObject);
            PrivateKeyInfo privateKeyInfo0 = PrivateKeyInfoFactory.CreatePrivateKeyInfo(DefalutPrivateKeyPassword, privateKeyInfo);
            AsymmetricKeyParameter privateKey = PrivateKeyFactory.CreateKey(privateKeyInfo0);
            engine.Init(false, privateKey);
            // 解密
            byte[] result = engine.ProcessBlock(cipherBytes, 0, cipherBytes.Length);
            return result;
        }

        public static byte[] Sign(byte[] key, byte[] data)
        {
            RsaDigestSigner signer = new RsaDigestSigner(new Sha256Digest());
            // 设置私钥
            byte[] key0 = key ?? DefalutPrivateByteKey;
            Asn1Object privateKeyObject = Asn1Object.FromByteArray(key0);
            EncryptedPrivateKeyInfo privateKeyInfo = EncryptedPrivateKeyInfo.GetInstance(privateKeyObject);
            PrivateKeyInfo privateKeyInfo0 = PrivateKeyInfoFactory.CreatePrivateKeyInfo(DefalutPrivateKeyPassword, privateKeyInfo);
            AsymmetricKeyParameter privateKey = PrivateKeyFactory.CreateKey(privateKeyInfo0);
            signer.Init(true, privateKey);
            // 签名
            signer.BlockUpdate(data, 0, data.Length);
            byte[] result = signer.GenerateSignature();
            return result;
        }

        public static bool VerifySign(byte[] key, byte[] data, byte[] sign)
        {
            RsaDigestSigner signer = new RsaDigestSigner(new Sha256Digest());
            // 设置公钥
            byte[] key0 = key ?? DefalutPublicByteKey;
            Asn1Object publicKeyObject = Asn1Object.FromByteArray(key0);
            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.GetInstance(publicKeyObject);
            AsymmetricKeyParameter publicKey = (RsaKeyParameters)PublicKeyFactory.CreateKey(publicKeyInfo);
            signer.Init(false, publicKey);
            // 验签
            signer.BlockUpdate(data, 0, data.Length);
            bool result = signer.VerifySignature(sign);
            return result;
        }

        public override byte[] EncryptToBytes(byte[] plainBytes, byte[] key = null)
        {
            return Encrypt(plainBytes, key);
        }

        public override byte[] DecryptFromBytes(byte[] cipherBytes, byte[] key = null)
        {
            return Decrypt(cipherBytes, key);
        }

        public override string GenerateKey()
        {
            KeyPair key = GetKeyPair();
            var publicBase64 = Convert.ToBase64String(key.PublicKey);
            var privateBase64 = Convert.ToBase64String(key.PrivateKey);
            var result = string.Format("{0};{1}", publicBase64, privateBase64);
            return result;
        }
    }
}
